#include "http/my_http_request.h"

void test_readline()
{
    my_buf_t *buf = my_buf_alloc_ext(128);
    strcpy(buf->end, "GET /1.txt");
    buf->end += sizeof("GET /1.txt") - 1;

    my_http_readline_sm_t sm;
    bzero(&sm, sizeof(my_http_readline_sm_t));

    if (my_http_readline(&sm, buf) != MY_AGAIN) {
        MY_LOG_FATAL("unexcept result");
    }

    strcpy(buf->end, " \r\n");
    buf->end += sizeof(" \r\n") - 1;
    buf->end += sizeof("GET /1.txt") - 1;
    if (my_http_readline(&sm, buf) != MY_SUCCESS) {
        MY_LOG_FATAL("unexcept result");
    }

    my_str_t str = {
        .data = "GET /1.txt \r\n",
        .len = sizeof("GET /1.txt \r\n") - 1
    };

    if (my_str_cmp(&sm.line, &str) != 0) {
        MY_LOG_FATAL("unexcept result");
    }

    strcpy(buf->end, "GET /1.txt");
    buf->end += sizeof("GET /1.txt");
    if (my_http_readline(&sm, buf) != MY_HTTP_READLINE_FAILED) {
        MY_LOG_FATAL("unexcept result");
    }

    my_buf_free(buf);
}

void test_parse_request_line()
{
    my_http_request_t request;

    bzero(&request, sizeof(my_http_request_t));
    MY_STR_SET(&request.readline_sm.line, "GET /1.txt");
    if (my_http_parse_request_line(&request) != MY_HTTP_INVALID_REQUEST_LINE) {
        MY_LOG_FATAL("unexcept result");
    }

    bzero(&request, sizeof(my_http_request_t));
    MY_STR_SET(&request.readline_sm.line, "GET /1.txt\n");

    if (my_http_parse_request_line(&request) != MY_SUCCESS ||
        request.method.len != 3 || strncmp(request.method.data, "GET", 3) != 0 ||
        request.raw_uri.len != 6 || strncmp(request.raw_uri.data, "/1.txt", 6) != 0 ||
        request.http_version != MY_HTTP_VERSION_9) {
        MY_LOG_FATAL("unexcept result");
    }

    bzero(&request, sizeof(my_http_request_t));
    MY_STR_SET(&request.readline_sm.line, "GET /1.txt\r\n");
    if (my_http_parse_request_line(&request) != MY_SUCCESS ||
        request.method.len != 3 || strncmp(request.method.data, "GET", 3) != 0 ||
        request.raw_uri.len != 6 || strncmp(request.raw_uri.data, "/1.txt", 6) != 0 ||
        request.http_version != MY_HTTP_VERSION_9) {
        MY_LOG_FATAL("unexcept result");
    }

    bzero(&request, sizeof(my_http_request_t));
    MY_STR_SET(&request.readline_sm.line, "GET /1.txt?a=1\n");
    if (my_http_parse_request_line(&request) != MY_SUCCESS ||
        request.method.len != 3 || strncmp(request.method.data, "GET", 3) != 0 ||
        request.raw_uri.len != 6 || strncmp(request.raw_uri.data, "/1.txt", 6) != 0 ||
        request.raw_args.len != 3 || strncmp(request.raw_args.data, "a=1", 3) != 0 ||
        request.http_version != MY_HTTP_VERSION_9) {
        MY_LOG_FATAL("unexcept result");
    }

    bzero(&request, sizeof(my_http_request_t));
    MY_STR_SET(&request.readline_sm.line, "GET /1.txt#frag\n");
    if (my_http_parse_request_line(&request) != MY_SUCCESS ||
        request.method.len != 3 || strncmp(request.method.data, "GET", 3) != 0 ||
        request.raw_uri.len != 6 || strncmp(request.raw_uri.data, "/1.txt", 6) != 0 ||
        request.raw_fragment.len != 4 || strncmp(request.raw_fragment.data, "frag", 4) != 0 ||
        request.http_version != MY_HTTP_VERSION_9) {
        MY_LOG_FATAL("unexcept result");
    }

    bzero(&request, sizeof(my_http_request_t));
    MY_STR_SET(&request.readline_sm.line, "GET /1.txt?a=1&b=2#frag\n");
    if (my_http_parse_request_line(&request) != MY_SUCCESS ||
        request.method.len != 3 || strncmp(request.method.data, "GET", 3) != 0 ||
        request.raw_uri.len != 6 || strncmp(request.raw_uri.data, "/1.txt", 6) != 0 ||
        request.raw_args.len != 7 || strncmp(request.raw_args.data, "a=1&b=2", 7) != 0 ||
        request.raw_fragment.len != 4 || strncmp(request.raw_fragment.data, "frag", 4) != 0 ||
        request.http_version != MY_HTTP_VERSION_9) {
        MY_LOG_FATAL("unexcept result");
    }

    bzero(&request, sizeof(my_http_request_t));
    MY_STR_SET(&request.readline_sm.line, "GET /1.txt?a=1#frag\r\n");
    if (my_http_parse_request_line(&request) != MY_SUCCESS ||
        request.method.len != 3 || strncmp(request.method.data, "GET", 3) != 0 ||
        request.raw_uri.len != 6 || strncmp(request.raw_uri.data, "/1.txt", 6) != 0 ||
        request.raw_args.len != 3 || strncmp(request.raw_args.data, "a=1", 3) != 0 ||
        request.raw_fragment.len != 4 || strncmp(request.raw_fragment.data, "frag", 4) != 0 ||
        request.http_version != MY_HTTP_VERSION_9) {
        MY_LOG_FATAL("unexcept result");
    }

    bzero(&request, sizeof(my_http_request_t));
    MY_STR_SET(&request.readline_sm.line, "GET /1.txt HTTP/1.1\r\n");
    if (my_http_parse_request_line(&request) != MY_SUCCESS ||
        request.method.len != 3 || strncmp(request.method.data, "GET", 3) != 0 ||
        request.raw_uri.len != 6 || strncmp(request.raw_uri.data, "/1.txt", 6) != 0 ||
        request.http_version != MY_HTTP_VERSION_11) {
        MY_LOG_FATAL("unexcept result");
    }

    bzero(&request, sizeof(my_http_request_t));
    MY_STR_SET(&request.readline_sm.line, "GET /1.txt?a=1#frag HTTP/1.1\r\n");
    if (my_http_parse_request_line(&request) != MY_SUCCESS ||
        request.method.len != 3 || strncmp(request.method.data, "GET", 3) != 0 ||
        request.raw_uri.len != 6 || strncmp(request.raw_uri.data, "/1.txt", 6) != 0 ||
        request.raw_args.len != 3 || strncmp(request.raw_args.data, "a=1", 3) != 0 ||
        request.raw_fragment.len != 4 || strncmp(request.raw_fragment.data, "frag", 4) != 0 ||
        request.http_version != MY_HTTP_VERSION_11) {
        MY_LOG_FATAL("unexcept result");
    }

    bzero(&request, sizeof(my_http_request_t));
    MY_STR_SET(&request.readline_sm.line, "GET http://www.a.com/1.txt?a=1#frag\n");
    if (my_http_parse_request_line(&request) != MY_SUCCESS ||
        request.method.len != 3 || strncmp(request.method.data, "GET", 3) != 0 ||
        request.connect_scheme.len != 4 || strncmp(request.connect_scheme.data, "http", 4) ||
        request.connect_host.len != 9 || strncmp(request.connect_host.data, "www.a.com", 9) ||
        request.raw_uri.len != 6 || strncmp(request.raw_uri.data, "/1.txt", 6) != 0 ||
        request.raw_args.len != 3 || strncmp(request.raw_args.data, "a=1", 3) != 0 ||
        request.raw_fragment.len != 4 || strncmp(request.raw_fragment.data, "frag", 4) != 0 ||
        request.http_version != MY_HTTP_VERSION_9) {
        MY_LOG_FATAL("unexcept result");
    }

    bzero(&request, sizeof(my_http_request_t));
    MY_STR_SET(&request.readline_sm.line, "GET https://www.a.com:80/1.txt?a=1#frag HTTP/1.1\r\n");
    if (my_http_parse_request_line(&request) != MY_SUCCESS ||
        request.method.len != 3 || strncmp(request.method.data, "GET", 3) != 0 ||
        request.connect_scheme.len != 5 || strncmp(request.connect_scheme.data, "https", 5) ||
        request.connect_host.len != 9 || strncmp(request.connect_host.data, "www.a.com", 9) ||
        request.connect_port.len != 2 || strncmp(request.connect_port.data, "80", 2) ||
        request.raw_uri.len != 6 || strncmp(request.raw_uri.data, "/1.txt", 6) != 0 ||
        request.raw_args.len != 3 || strncmp(request.raw_args.data, "a=1", 3) != 0 ||
        request.raw_fragment.len != 4 || strncmp(request.raw_fragment.data, "frag", 4) != 0 ||
        request.http_version != MY_HTTP_VERSION_11) {
        MY_LOG_FATAL("unexcept result");
    }

    bzero(&request, sizeof(my_http_request_t));
    MY_STR_SET(&request.readline_sm.line, "GET http://[1:1:1:1]:80/1.txt?a=1#frag HTTP/1.1\r\n");
    if (my_http_parse_request_line(&request) != MY_SUCCESS ||
        request.method.len != 3 || strncmp(request.method.data, "GET", 3) != 0 ||
        request.connect_scheme.len != 4 || strncmp(request.connect_scheme.data, "http", 4) ||
        request.connect_host.len != 7 || strncmp(request.connect_host.data, "1:1:1:1", 7) ||
        request.connect_port.len != 2 || strncmp(request.connect_port.data, "80", 2) ||
        request.raw_uri.len != 6 || strncmp(request.raw_uri.data, "/1.txt", 6) != 0 ||
        request.raw_args.len != 3 || strncmp(request.raw_args.data, "a=1", 3) != 0 ||
        request.raw_fragment.len != 4 || strncmp(request.raw_fragment.data, "frag", 4) != 0 ||
        request.http_version != MY_HTTP_VERSION_11) {
        MY_LOG_FATAL("unexcept result");
    }
}

void test_parse_header_line()
{
    my_http_header_t header;
    bzero(&header, sizeof(my_http_header_t));

    my_str_t line;

    MY_STR_SET(&line, " test: a\r\n");
    if (my_http_parse_header_line(&line, &header) != MY_HTTP_INVALID_HEADER_LINE) {
        MY_LOG_FATAL("unexcept result");
    }

    MY_STR_SET(&line, "test : a\r\n");
    if (my_http_parse_header_line(&line, &header) != MY_HTTP_INVALID_HEADER_LINE) {
        MY_LOG_FATAL("unexcept result");
    }

    MY_STR_SET(&line, "te st: a\r\n");
    if (my_http_parse_header_line(&line, &header) != MY_HTTP_INVALID_HEADER_LINE) {
        MY_LOG_FATAL("unexcept result");
    }

    MY_STR_SET(&line, "test: a\r\n");
    if (my_http_parse_header_line(&line, &header) != MY_SUCCESS ||
        header.name.len != 4 || strncmp(header.name.data, "test", 4) != 0 ||
        header.value.len != 1 || strncmp(header.value.data, "a", 1) != 0) {
        MY_LOG_FATAL("unexcept result");
    }

    MY_STR_SET(&line, "test: a  \r\n");
    if (my_http_parse_header_line(&line, &header) != MY_SUCCESS ||
        header.name.len != 4 || strncmp(header.name.data, "test", 4) != 0 ||
        header.value.len != 1 || strncmp(header.value.data, "a", 1) != 0) {
        MY_LOG_FATAL("unexcept result");
    }

    MY_STR_SET(&line, "test:a  \r\n");
    if (my_http_parse_header_line(&line, &header) != MY_SUCCESS ||
        header.name.len != 4 || strncmp(header.name.data, "test", 4) != 0 ||
        header.value.len != 1 || strncmp(header.value.data, "a", 1) != 0) {
        MY_LOG_FATAL("unexcept result");
    }

    MY_STR_SET(&line, "test:a b \r\n");
    if (my_http_parse_header_line(&line, &header) != MY_SUCCESS ||
        header.name.len != 4 || strncmp(header.name.data, "test", 4) != 0 ||
        header.value.len != 3 || strncmp(header.value.data, "a b", 1) != 0) {
        MY_LOG_FATAL("unexcept result");
    }
}

int main()
{
    test_readline();
    test_parse_request_line();
    test_parse_header_line();

    my_mem_assert_leak();

    MY_LOG_DEBUG("test pass");
    return 0;
}